﻿/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * Author: Laurent WOUTERS
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Hime.Redist.Parsers;

namespace xowl.gmi.compiler.transform
{
    class Transformation
    {
        private Dictionary<string, string> prefixes;
        private Dictionary<string, TransformationRule> cmRules;
        private Dictionary<string, TransformationRule> mvRules;
        private Dictionary<string, TransformationRule> vvRules;

        public void AddPrefix(string prefix, string uri) { prefixes.Add(prefix, uri); }

        public Transformation()
        {
            prefixes = new Dictionary<string, string>();
            cmRules = new Dictionary<string, TransformationRule>();
            mvRules = new Dictionary<string, TransformationRule>();
            vvRules = new Dictionary<string, TransformationRule>();
            CreateVVAttachConnector();
        }

        public Transformation(SyntaxTreeNode node)
        {
            prefixes = new Dictionary<string, string>();
            cmRules = new Dictionary<string, TransformationRule>();
            mvRules = new Dictionary<string, TransformationRule>();
            vvRules = new Dictionary<string, TransformationRule>();
            foreach (SyntaxTreeNode child in node.Children[0].Children)
            {
                string prefix = string.Empty;
                if (child.Children.Count == 2)
                    prefix = ((SymbolTokenText)child.Children[0].Symbol).ValueText;
                string uri = ((SymbolTokenText)child.Children[child.Children.Count - 1].Symbol).ValueText;
                AddPrefix(prefix, uri.Substring(1, uri.Length - 2));
            }
            foreach (SyntaxTreeNode child in node.Children[1].Children)
            {
                TransformationRule rule = new TransformationRule(child);
                if (rule.Direction == "cm")
                    cmRules.Add(rule.Name, rule);
                else if (rule.Direction == "mv")
                    mvRules.Add(rule.Name, rule);
                else
                    vvRules.Add(rule.Name, rule);
            }
            CreateVVAttachConnector();
        }

        public void Build(Dictionary<string, ast.ASTPattern> patterns)
        {
            foreach (string symbol in patterns.Keys)
            {
                ast.ASTPattern ast = patterns[symbol];
                CompileParameterCascading(ast);
                if (ast is ast.ASTPatternConnector)
                {
                    CompileConnector(ast as ast.ASTPatternConnector);
                    CompileSubRoot(ast);
                }
                else
                {
                    CreateCMCreateSubTree(symbol);
                    CreateCMDeleteSubTree(symbol);
                    CreateMVObjectToTrace(symbol);
                    CreateMVObjectToAST(symbol, patterns[symbol].GetMinimal());
                    CompileSubRoot(patterns[symbol]);
                }
            }
        }
        private void CompileSubRoot(ast.ASTPattern pattern)
        {
            List<ast.ASTPattern> roots = pattern.Split();
            List<ast.ASTPattern> explored = new List<ast.ASTPattern>();
            foreach (ast.ASTPattern rnode in roots)
            {
                if (explored.Contains(rnode))
                    continue;
                List<ast.ASTPattern> vars = rnode.GetVariableNodes();
                if (vars.Count == 1)
                {
                    if (vars[0] is ast.ASTPatternPlaceholder)
                    {
                        ast.ASTPatternPlaceholder placeholder = vars[0] as ast.ASTPatternPlaceholder;
                        CreateCMSetToken(placeholder.Route, placeholder.Property);
                        CreateCMUnsetToken(placeholder.Route, placeholder.Property);
                        CreateMVDataPropertyToAST(placeholder.Route, placeholder.Property, placeholder.Symbol);
                    }
                    else
                    {
                        ast.ASTPatternVariable node = vars[0] as ast.ASTPatternVariable;
                        Dictionary<string, string> parameters = new Dictionary<string, string>();
                        foreach (ast.Parameter param in node.Parameters)
                            if (param.ValueType != ast.ParameterValueType.Parameter)
                                parameters.Add(param.Name, param.ValueOWL);
                        CreateCMAttachSubTree(node.Symbol, node.ParentRoute, node.Property);
                        CreateCMDetachSubTree(node.Symbol, node.ParentRoute, node.Property);
                        CreateMVObjPropertyToAST(node.ParentRoute, node.Property, parameters);
                        if (node.IsOrdered)
                        {
                            CreateCMSetSubTreeOrder(node.Symbol, node.ParentRoute, node.Property);
                            CreateCMUnsetSubTreeOrder(node.Symbol, node.ParentRoute, node.Property);
                            CreateMVOrderToAST(node.ParentRoute, node.Property);
                        }
                    }
                }
                explored.Add(rnode);
            }
        }
        private void CompileConnector(ast.ASTPatternConnector connector)
        {
            ast.MinimalAST minimal = connector.GetMinimal();
            if (connector.HasChildren)
            {
                CreateCMConnectAssoc(connector.Symbol);
                CreateCMDisconnectAssoc(connector.Symbol);
                CreateMVAssocToTrace(connector.Symbol);
                CreateMVAssocToAST(connector.Symbol, minimal);
            }
            else
            {
                CreateCMConnectLink(connector.Symbol, connector.Property);
                CreateCMDisconnectLink(connector.Symbol, connector.Property);
                CreateMVLinkToTrace(connector.Symbol, connector.Property);
                CreateMVLinkToAST(connector.Symbol, connector.Property, minimal);
            }
        }
        private void CompileParameterCascading(ast.ASTPattern pattern)
        {
            List<ast.Cascade> cascades = pattern.GetCascades();
            foreach (ast.Cascade cascade in cascades)
                CreateVVParameterCascade(cascade.ParentSymbol, cascade.ChildSymbol, cascade.ParentParam, cascade.ChildParam);
        }

        private void CreateCMCreateSubTree(string symbol)
        {
            //      create(?n view:<symbol>)
            //      =>
            //      ClassAssertion(model:<symbol> ?o)
            // ^    from(?n ?o)
            // ^    trace(?n ?o)
            PatternVariable n = new PatternVariable("n");
            PatternVariable o = new PatternVariable("o");
            TransformationRule rule = new TransformationRule("CMCreateSubTree_" + symbol, "cm");
            rule.AddOnLeft(new PatternBuiltin("create", n, new Constant("view:" + symbol)));
            rule.AddOnRight(new PatternOWL("ClassAssertion", new Constant("model:" + symbol), o));
            rule.AddOnRight(new PatternBuiltin("from", n, o, true, false));
            rule.AddOnRight(new PatternBuiltin("trace", n, o, true, false));
            AddCMRule(rule);
        }
        private void CreateCMDeleteSubTree(string symbol)
        {
            //      delete(?n view:<symbol>)
            // ^    trace(?n ?o)
            //      =>
            //   -  ClassAssertion(model:<symbol> ?o)
            // ^ -  from(?n ?o)
            // ^ -  trace(?n ?o)
            PatternVariable n = new PatternVariable("n");
            PatternVariable o = new PatternVariable("o");
            TransformationRule rule = new TransformationRule("CMDeleteSubTree_" + symbol, "cm");
            rule.AddOnLeft(new PatternBuiltin("delete", n, new Constant("view:" + symbol)));
            rule.AddOnLeft(new PatternBuiltin("trace", n, o, true, false));
            rule.AddOnRight(new PatternOWL("ClassAssertion", new Constant("model:" + symbol), o, false, true));
            rule.AddOnRight(new PatternBuiltin("from", n, o, true, true));
            rule.AddOnRight(new PatternBuiltin("trace", n, o, true, true));
            AddCMRule(rule);
        }
        private void CreateMVObjectToTrace(string symbol)
        {
            //      ClassAssertion(model:<symbol> ?o)
            // ^ -  from(?x ?o)
            //      =>
            // ^    trace(?n ?o)
            PatternVariable n = new PatternVariable("n");
            PatternVariable x = new PatternVariable("x");
            PatternVariable o = new PatternVariable("o");
            TransformationRule rule = new TransformationRule("MVObjectToTrace_" + symbol, "mv");
            rule.AddOnLeft(new PatternOWL("ClassAssertion", new Constant("model:" + symbol), o));
            rule.AddOnLeft(new PatternBuiltin("from", x, o, true, true));
            rule.AddOnRight(new PatternBuiltin("trace", n, o, true, false));
            AddMVRule(rule);
        }
        private void CreateMVObjectToAST(string symbol, ast.MinimalAST ast)
        {
            //      ClassAssertion(model:<symbol> ?o)
            // ^    trace(?n ?o)
            //      =>
            //      MinimalAST(?n view:<symbol>)
            PatternVariable n = new PatternVariable("n");
            PatternVariable o = new PatternVariable("o");
            TransformationRule rule = new TransformationRule("MVObjectToAST_" + symbol, "mv");
            rule.AddOnLeft(new PatternOWL("ClassAssertion", new Constant("model:" + symbol), o));
            rule.AddOnLeft(new PatternBuiltin("trace", n, o, true, false));
            rule.AddOnRight(new PatternAST(n, ast));
            AddMVRule(rule);
        }

        private void CreateCMAttachSubTree(string symbol, string route, string property)
        {
            //      attach(view:<symbol> ?np ?nc)
            // ^    route(view:<route> ?nr ?np)
            // ^    trace(?nr ?or)
            // ^    trace(?nc ?oc)
            //      =>
            //      ObjectPropertyAssertion(model:<property> ?or ?oc)
            PatternVariable np = new PatternVariable("np");
            PatternVariable nc = new PatternVariable("nc");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable or = new PatternVariable("or");
            PatternVariable oc = new PatternVariable("oc");
            TransformationRule rule = new TransformationRule("CMAttachSubTree_" + symbol + "_" + route, "cm");
            rule.AddOnLeft(new PatternBuiltin("attach", new Constant("view:" + symbol), np, nc));
            rule.AddOnLeft(new PatternBuiltin("route", new Constant("view:" + route), nr, np, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nc, oc, true, false));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + property), or, oc));
            AddCMRule(rule);
        }
        private void CreateCMDetachSubTree(string symbol, string route, string property)
        {
            //      detach(view:<symbol> ?np ?nc)
            // ^    route(view:<route> ?nr ?np)
            // ^    trace(?nr ?or)
            // ^    trace(?nc ?oc)
            //      =>
            //   -  ObjectPropertyAssertion(model:<property> ?or ?oc)
            PatternVariable np = new PatternVariable("np");
            PatternVariable nc = new PatternVariable("nc");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable or = new PatternVariable("or");
            PatternVariable oc = new PatternVariable("oc");
            TransformationRule rule = new TransformationRule("CMDetachSubTree_" + symbol + "_" + route, "cm");
            rule.AddOnLeft(new PatternBuiltin("detach", new Constant("view:" + symbol), np, nc));
            rule.AddOnLeft(new PatternBuiltin("route", new Constant("view:" + route), nr, np, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nc, oc, true, false));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + property), or, oc, false, true));
            AddCMRule(rule);
        }
        private void CreateMVObjPropertyToAST(string route, string property, Dictionary<string, string> parameters)
        {
            //      ObjectPropertyAssertion(model:<property> ?or ?oc)
            // ^    trace(?nr ?or)
            // ^    trace(?nc ?oc)
            // ^    route(view:<route> ?nr ?np)
            //      =>
            //      ObjectPropertyAssertion(ast:children ?np ?nc)
            // ^    ClassAssertion(ast:Decorator ?d)
            // ^    ObjectPropertyAssertion(ast:decorators ?nc ?d)
            // ^    ObjectPropertyAssertion(ast:parent ?d ?np)
            // ^    DataPropertyAssertion(view:<param_i> ?d <value_i>)
            PatternVariable np = new PatternVariable("np");
            PatternVariable nc = new PatternVariable("nc");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable or = new PatternVariable("or");
            PatternVariable oc = new PatternVariable("oc");
            PatternVariable d = new PatternVariable("d");
            TransformationRule rule = new TransformationRule("MVObjPropertyToAST_" + route + "_" + property, "mv");
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + property), or, oc));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nc, oc, true, false));
            rule.AddOnLeft(new PatternBuiltin("route", new Constant("view:" + route), nr, np, true, false));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:children"), np, nc));
            rule.AddOnRight(new PatternOWL("ClassAssertion", new Constant("ast:Decorator"), d, true, false));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:decorators"), nc, d, true, false));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:parent"), d, np, true, false));
            foreach (string name in parameters.Keys)
                rule.AddOnRight(new PatternOWL("DataPropertyAssertion", new Constant("view:" + name), d, new Constant(parameters[name]), true, false));
            AddMVRule(rule);
        }

        private void CreateCMSetSubTreeOrder(string symbol, string route, string property)
        {
            //      order(view:<symbol> ?np ?nc ?i)
            // ^    route(view:<route> ?nr ?np)
            // ^    trace(?nr ?or)
            // ^    trace(?nc ?oc)
            //      =>
            //      indexer(?ind model:<property> ?or ?oc ?i)
            PatternVariable np = new PatternVariable("np");
            PatternVariable nc = new PatternVariable("nc");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable or = new PatternVariable("or");
            PatternVariable oc = new PatternVariable("oc");
            PatternVariable ind = new PatternVariable("ind");
            PatternVariable i = new PatternVariable("i");
            TransformationRule rule = new TransformationRule("CMSetSubTreeOrder_" + symbol + "_" + route, "cm");
            rule.AddOnLeft(new PatternBuiltin("order", new Constant("view:" + symbol), np, nc, i));
            rule.AddOnLeft(new PatternBuiltin("route", new Constant("view:" + route), nr, np, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nc, oc, true, false));
            rule.AddOnRight(new PatternBuiltin("indexer", ind, new Constant("model:" + property), or, oc, i));
            AddCMRule(rule);
        }
        private void CreateCMUnsetSubTreeOrder(string symbol, string route, string property)
        {
            //      unorder(view:<symbol> ?np ?nc ?i)
            // ^    route(view:<route> ?nr ?np)
            // ^    trace(?nr ?or)
            // ^    trace(?nc ?oc)
            // ^    from(?nc ?ind)
            // ^    indexer(?ind model:<property> ?or ?oc ?i)
            //      =>
            //   -  indexer(?ind model:<property> ?or ?oc ?i)
            PatternVariable np = new PatternVariable("np");
            PatternVariable nc = new PatternVariable("nc");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable or = new PatternVariable("or");
            PatternVariable oc = new PatternVariable("oc");
            PatternVariable ind = new PatternVariable("ind");
            PatternVariable i = new PatternVariable("i");
            TransformationRule rule = new TransformationRule("CMUnsetSubTreeOrder_" + symbol + "_" + route, "cm");
            rule.AddOnLeft(new PatternBuiltin("unorder", new Constant("view:" + symbol), np, nc, i));
            rule.AddOnLeft(new PatternBuiltin("route", new Constant("view:" + route), nr, np, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nc, oc, true, false));
            rule.AddOnLeft(new PatternBuiltin("indexer", ind, new Constant("model:" + property), or, oc, i, true, false));
            rule.AddOnRight(new PatternBuiltin("indexer", ind, new Constant("model:" + property), or, oc, i, false, true));
            AddCMRule(rule);
        }
        private void CreateMVOrderToAST(string route, string property)
        {
            //      ObjectPropertyAssertion(model:<property> ?or ?oc)
            //      indexer(?ind model:<property> ?or ?oc ?i)
            // ^    trace(?nr ?or)
            // ^    trace(?nc ?oc)
            // ^    route(view:<route> ?nr ?np)
            // ^    ObjectPropertyAssertion(ast:decorators ?nc ?d)
            // ^    ObjectPropertyAssertion(ast:parent ?d ?np)
            //      =>
            // ^    DataPropertyAssertion(ast:index ?d ?i)
            // ^    indexer(?ind model:<property> ?or ?oc ?i)
            PatternVariable np = new PatternVariable("np");
            PatternVariable nc = new PatternVariable("nc");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable or = new PatternVariable("or");
            PatternVariable oc = new PatternVariable("oc");
            PatternVariable d = new PatternVariable("d");
            PatternVariable ind = new PatternVariable("ind");
            PatternVariable i = new PatternVariable("i");
            TransformationRule rule = new TransformationRule("MVOrderToAST_" + route + "_" + property, "mv");
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + property), or, oc));
            rule.AddOnLeft(new PatternBuiltin("indexer", ind, new Constant("model:" + property), or, oc, i));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nc, oc, true, false));
            rule.AddOnLeft(new PatternBuiltin("route", new Constant("view:" + route), nr, np, true, false));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:decorators"), nc, d, true, false));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:parent"), d, np, true, false));
            rule.AddOnRight(new PatternOWL("DataPropertyAssertion", new Constant("ast:index"), d, i, true, false));
            rule.AddOnRight(new PatternBuiltin("indexer", ind, new Constant("model:" + property), or, oc, i, true, false));
            AddMVRule(rule);
        }

        private void CreateCMSetToken(string route, string property)
        {
            //      set(?n ?v)
            // ^    route(view:<route> ?nr ?n)
            // ^    trace(?nr ?o)
            //      =>
            //      DataPropertyAssertion(model:<property> ?o ?v)
            PatternVariable n = new PatternVariable("n");
            PatternVariable v = new PatternVariable("v");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable o = new PatternVariable("o");
            TransformationRule rule = new TransformationRule("CMSetToken_" + route + "_" + property, "cm");
            rule.AddOnLeft(new PatternBuiltin("set", n, v));
            rule.AddOnLeft(new PatternBuiltin("route", new Constant("view:" + route), nr, n, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, o, true, false));
            rule.AddOnRight(new PatternOWL("DataPropertyAssertion", new Constant("model:" + property), o, v));
            AddCMRule(rule);
        }
        private void CreateCMUnsetToken(string route, string property)
        {
            //      unset(?n ?v)
            // ^    route(view:<route> ?nr ?n)
            // ^    trace(?nr ?o)
            //      =>
            //   -  DataPropertyAssertion(model:<property> ?o ?v)
            PatternVariable n = new PatternVariable("n");
            PatternVariable v = new PatternVariable("v");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable o = new PatternVariable("o");
            TransformationRule rule = new TransformationRule("CMUnsetToken_" + route + "_" + property, "cm");
            rule.AddOnLeft(new PatternBuiltin("unset", n, v));
            rule.AddOnLeft(new PatternBuiltin("route", new Constant("view:" + route), nr, n, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, o, true, false));
            rule.AddOnRight(new PatternOWL("DataPropertyAssertion", new Constant("model:" + property), o, v, false, true));
            AddCMRule(rule);
        }
        private void CreateMVDataPropertyToAST(string route, string property, string type)
        {
            //      DataPropertyAssertion(model:<property> ?o ?v)
            // ^    trace(?nr ?o)
            // ^    route(view:<route> ?nr ?n)
            // ^    token(?n ?t)
            //      =>
            //      DataPropertyAssertion(ast:data<type> ?t ?v)
            PatternVariable o = new PatternVariable("o");
            PatternVariable v = new PatternVariable("v");
            PatternVariable n = new PatternVariable("n");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable t = new PatternVariable("t");
            TransformationRule rule = new TransformationRule("MVDataPropertyToAST_" + route + "_" + property, "mv");
            rule.AddOnLeft(new PatternOWL("DataPropertyAssertion", new Constant("model:" + property), o, v));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, o, true, false));
            rule.AddOnLeft(new PatternBuiltin("route", new Constant("view:" + route), nr, n, true, false));
            rule.AddOnLeft(new PatternBuiltin("token", n, t, true, false));
            rule.AddOnRight(new PatternOWL("DataPropertyAssertion", new Constant("ast:data" + type), t, v));
            AddMVRule(rule);
        }

        private void CreateCMConnectLink(string connector, string property)
        {
            //      connect(view:<connector> ?cn ?nl ?nr)
            // ^    trace(?nl ?ol)
            // ^    trace(?nr ?or)
            //      =>
            //      ObjectPropertyAssertion(model:<property> ?ol ?or)
            // ^    lfrom(?cn model:<property> ?ol ?or)
            // ^    ltrace(?cn model:<property> ?ol ?or)
            PatternVariable cn = new PatternVariable("cn");
            PatternVariable nl = new PatternVariable("nl");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable ol = new PatternVariable("ol");
            PatternVariable or = new PatternVariable("or");
            TransformationRule rule = new TransformationRule("CMConnectLink_" + connector + "_" + property, "cm");
            rule.AddOnLeft(new PatternBuiltin("connect", new Constant("view:" + connector), cn, nl, nr));
            rule.AddOnLeft(new PatternBuiltin("trace", nl, ol, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + property), ol, or));
            rule.AddOnRight(new PatternBuiltin("lfrom", cn, new Constant("model:" + property), ol, or, true, false));
            rule.AddOnRight(new PatternBuiltin("ltrace", cn, new Constant("model:" + property), ol, or, true, false));
            AddCMRule(rule);
        }
        private void CreateCMDisconnectLink(string connector, string property)
        {
            //      disconnect(view:<connector> ?cn ?nl ?nr)
            // ^    trace(?nl ?ol)
            // ^    trace(?nr ?or)
            // ^    ltrace(?cn model:<property> ?ol ?or)
            //      =>
            //   -  ObjectPropertyAssertion(model:<property> ?ol ?or)
            // ^ -  lfrom(?cn model:<property> ?ol ?or)
            // ^ -  ltrace(?cn model:<property> ?ol ?or)
            PatternVariable cn = new PatternVariable("cn");
            PatternVariable nl = new PatternVariable("nl");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable ol = new PatternVariable("ol");
            PatternVariable or = new PatternVariable("or");
            TransformationRule rule = new TransformationRule("CMDisconnectLink_" + connector + "_" + property, "cm");
            rule.AddOnLeft(new PatternBuiltin("disconnect", new Constant("view:" + connector), cn, nl, nr));
            rule.AddOnLeft(new PatternBuiltin("trace", nl, ol, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnLeft(new PatternBuiltin("ltrace", cn, new Constant("model:" + property), ol, or, true, false));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + property), ol, or, false, true));
            rule.AddOnRight(new PatternBuiltin("lfrom", cn, new Constant("model:" + property), ol, or, true, true));
            rule.AddOnRight(new PatternBuiltin("ltrace", cn, new Constant("model:" + property), ol, or, true, true));
            AddCMRule(rule);
        }
        private void CreateMVLinkToTrace(string connector, string property)
        {
            //      ObjectPropertyAssertion(model:<property> ?ol ?or)
            // ^ -  lfrom(?x model:<property> ?ol ?or)
            //      =>
            // ^    ltrace(?cn model:<property> ?ol ?or)
            PatternVariable x = new PatternVariable("x");
            PatternVariable cn = new PatternVariable("cn");
            PatternVariable ol = new PatternVariable("ol");
            PatternVariable or = new PatternVariable("or");
            TransformationRule rule = new TransformationRule("MVLinkToTrace_" + connector + "_" + property, "mv");
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + property), ol, or));
            rule.AddOnLeft(new PatternBuiltin("lfrom", x, new Constant("model:" + property), ol, or, true, true));
            rule.AddOnRight(new PatternBuiltin("ltrace", cn, new Constant("model:" + property), ol, or, true, false));
            AddMVRule(rule);
        }
        private void CreateMVLinkToAST(string connector, string property, ast.MinimalAST ast)
        {
            //      ObjectPropertyAssertion(model:<property> ?ol ?or)
            // ^    ltrace(?cn model:<property> ?ol ?or)
            // ^    trace(?nl ?ol)
            // ^    trace(?nr ?or)
            //      =>
            //      MinimalAST(?cn view:<connector>)
            //      ObjectPropertyAssertion(ast:originChild ?cn ?nl)
            //      ObjectPropertyAssertion(ast:targetChild ?cn ?nr)
            PatternVariable cn = new PatternVariable("cn");
            PatternVariable nl = new PatternVariable("nl");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable ol = new PatternVariable("ol");
            PatternVariable or = new PatternVariable("or");
            TransformationRule rule = new TransformationRule("MVLinkToAST_" + connector + "_" + property, "mv");
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + property), ol, or));
            rule.AddOnLeft(new PatternBuiltin("ltrace", cn, new Constant("model:" + property), ol, or, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nl, ol, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnRight(new PatternAST(cn, ast));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:originChild"), cn, nl));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:targetChild"), cn, nr));
            AddMVRule(rule);
        }

        private void CreateCMConnectAssoc(string connector)
        {
            //      connect(view:<connector> ?cn ?nl ?nr)
            // ^    trace(?nl ?ol)
            // ^    trace(?nr ?or)
            //      =>
            // ^    from(?cn ?c)
            // ^    trace(?cn ?c)
            //      ClassAssertion(model:<connector> ?c)
            //      ObjectPropertyAssertion(model:<connector>_origin ?c ?ol)
            //      ObjectPropertyAssertion(model:<connector>_target ?c ?or)
            PatternVariable cn = new PatternVariable("cn");
            PatternVariable nl = new PatternVariable("nl");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable ol = new PatternVariable("ol");
            PatternVariable or = new PatternVariable("or");
            PatternVariable c = new PatternVariable("c");
            TransformationRule rule = new TransformationRule("CMConnectAssoc_" + connector, "cm");
            rule.AddOnLeft(new PatternBuiltin("connect", new Constant("view:" + connector), cn, nl, nr));
            rule.AddOnLeft(new PatternBuiltin("trace", nl, ol, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnRight(new PatternBuiltin("from", cn, c, true, false));
            rule.AddOnRight(new PatternBuiltin("trace", cn, c, true, false));
            rule.AddOnRight(new PatternOWL("ClassAssertion", new Constant("model:" + connector), c));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + connector + "_origin"), c, ol));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + connector + "_target"), c, or));
            AddCMRule(rule);
        }
        private void CreateCMDisconnectAssoc(string connector)
        {
            //      disconnect(view:<connector> ?cn ?nl ?nr)
            // ^    trace(?cn ?c)
            // ^    trace(?nl ?ol)
            // ^    trace(?nr ?or)
            //      =>
            // ^ -  from(?cn ?c)
            // ^ -  trace(?cn ?c)
            //   -  ClassAssertion(model:<connector> ?c)
            //   -  ObjectPropertyAssertion(model:<connector>_origin ?c ?ol)
            //   -  ObjectPropertyAssertion(model:<connector>_target ?c ?or)
            PatternVariable cn = new PatternVariable("cn");
            PatternVariable nl = new PatternVariable("nl");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable ol = new PatternVariable("ol");
            PatternVariable or = new PatternVariable("or");
            PatternVariable c = new PatternVariable("c");
            TransformationRule rule = new TransformationRule("CMDisconnectAssoc_" + connector, "cm");
            rule.AddOnLeft(new PatternBuiltin("disconnect", new Constant("view:" + connector), cn, nl, nr));
            rule.AddOnLeft(new PatternBuiltin("trace", cn, c, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nl, ol, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnRight(new PatternBuiltin("from", cn, c, true, true));
            rule.AddOnRight(new PatternBuiltin("trace", cn, c, true, true));
            rule.AddOnRight(new PatternOWL("ClassAssertion", new Constant("model:" + connector), c, false, true));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + connector + "_origin"), c, ol, false, true));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + connector + "_target"), c, or, false, true));
            AddCMRule(rule);
        }
        private void CreateMVAssocToTrace(string connector)
        {
            //      ClassAssertion(model:<connector> ?c)
            // ^ -  from(?x ?c)
            //      =>
            // ^    trace(?cn ?c)
            PatternVariable x = new PatternVariable("x");
            PatternVariable cn = new PatternVariable("cn");
            PatternVariable c = new PatternVariable("c");
            TransformationRule rule = new TransformationRule("MVAssocToTrace_" + connector, "mv");
            rule.AddOnLeft(new PatternOWL("ClassAssertion", new Constant("model:" + connector), c));
            rule.AddOnLeft(new PatternBuiltin("from", x, c, true, true));
            rule.AddOnRight(new PatternBuiltin("trace", cn, c, true, false));
            AddMVRule(rule);
        }
        private void CreateMVAssocToAST(string connector, ast.MinimalAST ast)
        {
            //      ClassAssertion(model:<connector> ?c)
            //      ObjectPropertyAssertion(model:<connector>_origin ?c ?ol)
            //      ObjectPropertyAssertion(model:<connector>_target ?c ?or)
            // ^    trace(?cn ?c)
            // ^    trace(?nl ?ol)
            // ^    trace(?nr ?or)
            //      =>
            //      MinimalAST(?n view:<connector>)
            //      ObjectPropertyAssertion(ast:originChild ?n ?nl)
            //      ObjectPropertyAssertion(ast:targetChild ?n ?nr)
            PatternVariable cn = new PatternVariable("cn");
            PatternVariable nl = new PatternVariable("nl");
            PatternVariable nr = new PatternVariable("nr");
            PatternVariable ol = new PatternVariable("ol");
            PatternVariable or = new PatternVariable("or");
            PatternVariable c = new PatternVariable("c");
            TransformationRule rule = new TransformationRule("MVAssocToAST_" + connector, "mv");
            rule.AddOnLeft(new PatternOWL("ClassAssertion", new Constant("model:" + connector), c));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + connector + "_origin"), c, ol));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("model:" + connector + "_target"), c, or));
            rule.AddOnLeft(new PatternBuiltin("trace", cn, c, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nl, ol, true, false));
            rule.AddOnLeft(new PatternBuiltin("trace", nr, or, true, false));
            rule.AddOnRight(new PatternAST(cn, ast));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:originChild"), cn, nl));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:targetChild"), cn, nr));
            AddMVRule(rule);
        }

        private void CreateVVAttachConnector()
        {
            //      ObjectPropertyAssertion(ast:originChild ?c ?wl)
            //      ObjectPropertyAssertion(ast:targetChild ?c ?wr)
            //      ObjectPropertyAssertion(ast:children ?g ?wl)
            //      ObjectPropertyAssertion(ast:children ?g ?wr)
            //      =>
            //      ObjectPropertyAssertion(ast:children ?g ?c)
            // ^    ClassAssertion(ast:Decorator ?d)
            // ^    ObjectPropertyAssertion(ast:decorators ?c ?d)
            // ^    ObjectPropertyAssertion(ast:parent ?d ?g)
            PatternVariable c = new PatternVariable("c");
            PatternVariable wl = new PatternVariable("wl");
            PatternVariable wr = new PatternVariable("wr");
            PatternVariable g = new PatternVariable("g");
            PatternVariable d = new PatternVariable("d");
            TransformationRule rule = new TransformationRule("VVAttachConnector", "vv");
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:originChild"), c, wl));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:targetChild"), c, wr));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:children"), g, wl));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:children"), g, wr));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:children"), g, c));
            rule.AddOnRight(new PatternOWL("ClassAssertion", new Constant("ast:Decorator"), d, true, false));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:decorators"), c, d, true, false));
            rule.AddOnRight(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:parent"), d, g, true, false));
            AddVVRule(rule);
        }

        private void CreateVVParameterCascade(string parent, string child, string p1, string p2)
        {
            //      ObjectPropertyAssertion(ast:children ?p ?c)
            //      ObjectPropertyAssertion(ast:symbol ?p view:<parent>)
            //      ObjectPropertyAssertion(ast:symbol ?c view:<child>)
            // ^    ObjectPropertyAssertion(ast:decorators ?c ?dc)
            // ^    ObjectPropertyAssertion(ast:decorators ?p ?dp)
            // ^    ObjectPropertyAssertion(ast:parent ?dc ?p)
            // ^    DataPropertyAssertion(view:<param1> ?dp ?v)
            //      =>
            // ^    DataPropertyAssertion(view:<param2> ?dc ?v)
            PatternVariable p = new PatternVariable("p");
            PatternVariable c = new PatternVariable("c");
            PatternVariable dp = new PatternVariable("dp");
            PatternVariable dc = new PatternVariable("dc");
            PatternVariable v = new PatternVariable("v");
            TransformationRule rule = new TransformationRule("VVParameterCascade_" + parent + "_" + child + "_" + p2, "vv");
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:children"), p, c));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:symbol"), p, new Constant("view:" + parent)));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:symbol"), c, new Constant("view:" + child)));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:decorators"), c, dc, true, false));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:decorators"), p, dp, true, false));
            rule.AddOnLeft(new PatternOWL("ObjectPropertyAssertion", new Constant("ast:parent"), dc, p, true, false));
            rule.AddOnLeft(new PatternOWL("DataPropertyAssertion", new Constant("view:" + p1), dp, v, true, false));
            rule.AddOnRight(new PatternOWL("DataPropertyAssertion", new Constant("view:" + p2), dc, v, true, false));
            AddVVRule(rule);
        }

        private void AddCMRule(TransformationRule rule)
        {
            if (!cmRules.ContainsKey(rule.Name))
                cmRules.Add(rule.Name, rule);
        }
        private void AddMVRule(TransformationRule rule)
        {
            if (!mvRules.ContainsKey(rule.Name))
                mvRules.Add(rule.Name, rule);
        }
        private void AddVVRule(TransformationRule rule)
        {
            if (!vvRules.ContainsKey(rule.Name))
                vvRules.Add(rule.Name, rule);
        }

        public void Write(StreamWriter writer)
        {
            writer.WriteLine("transformation {");
            foreach (string prefix in prefixes.Keys)
            {
                writer.Write("\t" + prefix + " := ");
                writer.WriteLine("\"" + prefixes[prefix] + "\"");
            }
            foreach (TransformationRule rule in cmRules.Values)
            {
                writer.WriteLine();
                rule.Write(writer);
            }
            foreach (TransformationRule rule in mvRules.Values)
            {
                writer.WriteLine();
                rule.Write(writer);
            }
            foreach (TransformationRule rule in vvRules.Values)
            {
                writer.WriteLine();
                rule.Write(writer);
            }
            writer.WriteLine("}");
        }

        public void WriteCMOWL(StreamWriter writer)
        {
            foreach (string prefix in prefixes.Keys)
                writer.WriteLine("Prefix(" + prefix + ":=<" + prefixes[prefix] + "#>)");
            writer.WriteLine("Ontology(<" + prefixes[string.Empty] + ">");
            foreach (TransformationRule rule in cmRules.Values)
            {
                writer.WriteLine();
                rule.WriteOWL(writer);
            }
            writer.WriteLine(")");
        }
        public void WriteMVOWL(StreamWriter writer)
        {
            foreach (string prefix in prefixes.Keys)
                writer.WriteLine("Prefix(" + prefix + ":=<" + prefixes[prefix] + "#>)");
            writer.WriteLine("Ontology(<" + prefixes[string.Empty] + ">");
            foreach (TransformationRule rule in mvRules.Values)
            {
                writer.WriteLine();
                rule.WriteOWL(writer);
            }
            writer.WriteLine(")");
        }
        public void WriteVVOWL(StreamWriter writer)
        {
            foreach (string prefix in prefixes.Keys)
                writer.WriteLine("Prefix(" + prefix + ":=<" + prefixes[prefix] + "#>)");
            writer.WriteLine("Ontology(<" + prefixes[string.Empty] + ">");
            foreach (TransformationRule rule in vvRules.Values)
            {
                writer.WriteLine();
                rule.WriteOWL(writer);
            }
            writer.WriteLine(")");
        }
    }
}
